/*
 * $Id: TestADIFLexer_old.m 58 2009-06-01 02:51:41Z jon@bway.net $
 * Chalk
 *
 * Created 5/31/09
 * Copyright Jon Gordon
 * 
 * Permission is hereby granted, free of charge, to any person obtaining 
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including 
 * without limitation the rights to use, copy, modify, merge, publish, 
 * distribute, sublicense, and/or sell copies of the Software, and to 
 * permit persons to whom the Software is furnished to do so, subject to 
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#import "TestADIFLexer.h"

#import "QEADIFInternal.h"

#import "QEADIFLexer.h"

static const NSString *EMPTY_STRING = @"";

static NSString *ADIF_SRC1_LF = @"<CALL:6>cx4aaj\n<BAND:3>15M\n<MODE:4>RTTY\n<QSO_DATE:8>20080928\n<TIME_ON:6>183200\n<FREQ:6>21.106\n<EOR>\n<CALL:4>n2bj\n<BAND:3>40M\n<MODE:5>PSK31\n<QSO_DATE:8>20081004\n<TIME_ON:6>000000\n<FREQ:5>7.072\n<EOR>\n<CALL:5>ai4of\n<BAND:3>40M\n<MODE:5>PSK31\n<QSO_DATE:8>20081004\n<TIME_ON:6>010700\n<FREQ:5>7.072\n<EOR>\n";

static NSArray *ADIF_SRC1_LF_TAGS;


@implementation TestADIFLexer
- (void)setUp
{
    NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    [super setUp];
    
    ADIF_SRC1_LF_TAGS = [[NSArray arrayWithObjects:
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"CALL\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"6\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"cx4aaj\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"BAND\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"3\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"15M\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"MODE\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"4\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"RTTY\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"QSO_DATE\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"8\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"20080928\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"TIME_ON\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"6\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"183200\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"FREQ\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"6\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"21.106\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"EOR\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<COMMENT>\"CALL\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"4\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"n2bj\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"BAND\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"3\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"40M\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"MODE\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"5\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"PSK31\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"QSO_DATE\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"8\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"20081004\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"TIME_ON\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"6\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"000000\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"FREQ\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"5\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"7.072\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"EOR\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"CALL\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"5\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"ai4of\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"BAND\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"3\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"40M\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"MODE\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"5\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"PSK31\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"QSO_DATE\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"8\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"20081004\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"TIME_ON\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"6\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"010700\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"FREQ\"}",
                          @"{lexeme:<SEPARATOR>\":\"}",
                          @"{lexeme:<NUMBER>\"5\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<TEXT>\"7.072\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:<OPEN>\"<\"}",
                          @"{lexeme:<TAG>\"EOR\"}",
                          @"{lexeme:<CLOSE>\">\"}",
                          @"{lexeme:<COMMENT>\"\n\"}",
                          @"{lexeme:EOI}"
                          nil] retain];
} // setUp

- (void)tearDown
{
    NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    [ADIF_SRC1_LF_TAGS release];
    
    [super tearDown];
}

 - (void)testBlankSource
{
    NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    QEADIFLexer *lexer = [[QEADIFLexer alloc] init];
    STAssertNotNil(lexer, @"ASSERT: failed to allocate lexer with default initializer");
    
    /*
     * Creating a lexer with the default initializer should be equivalent to creating
     * a lexer with a nil source text, which should in turn be equivalent to creating
     * a lexer with a zero-length, non-nil source text.  In all three cases, the
     * first element provided ought to be the End-Of-Input element, and all subsequent
     * elements ought to be nil.
     */
    QEADIFElement *e = [lexer nextElement];
    STAssertNotNil(e, @"ASSERT: returned nil element instead of expected EOInput element");
    if (nil != e) {
        STAssertTrue([e isEOInput], @"ASSERT: returned element (%@) should test true for EOInput");
        STAssertTrue(1 == [e startLine], @"ASSERT: element startLine should be 1 but it is %u",
                     [e startLine]);
        STAssertTrue(1 == [e startPos], @"ASSERT: element startPos should be 1 but it is %u",
                     [e startPos]);
        STAssertFalse([e isField], @"ASSERT: returned element (%@) should test false for Field");
        STAssertFalse([e isTag], @"ASSERT: returned element (%@) should test false for Tag");
        STAssertFalse([e isComment], @"ASSERT: returned element (%@) should test false for Comment");
        STAssertNotNil([e srcTxt], @"ASSERT: srcTxt should not be nil");
        if (nil != [e srcTxt]) {
            STAssertEqualObjects(EMPTY_STRING, 
                                 [e srcTxt], 
                                 @"srcText should be empty string but it \"%@\" instead", 
                                 [e srcTxt]);
        } // if
    } // if
    
    e = [lexer nextElement];
    STAssertNil(e, @"ASSERT: returned element should be nil, but is %@", e);
    
    [lexer release];
    
    lexer = [[QEADIFLexer alloc] initWithSrc:nil];
    STAssertNotNil(lexer, @"ASSERT: failed to allocate lexer when using empty string as source");
    
    /*
     * Creating a lexer with the default initializer should be equivalent to creating
     * a lexer with a nil source text, which should in turn be equivalent to creating
     * a lexer with a zero-length, non-nil source text.  In all three cases, the
     * first element provided ought to be the End-Of-Input element, and all subsequent
     * elements ought to be nil.
     */
    e = [lexer nextElement];
    STAssertNotNil(e, @"ASSERT: returned nil element instead of expected EOInput element");
    if (nil != e) {
        STAssertTrue([e isEOInput], @"ASSERT: returned element (%@) should test true for EOInput");
        STAssertTrue(1 == [e startLine], @"ASSERT: element startLine should be 1 but it is %u",
                     [e startLine]);
        STAssertTrue(1 == [e startPos], @"ASSERT: element startPos should be 1 but it is %u",
                     [e startPos]);
        STAssertFalse([e isField], @"ASSERT: returned element (%@) should test false for Field");
        STAssertFalse([e isTag], @"ASSERT: returned element (%@) should test false for Tag");
        STAssertFalse([e isComment], @"ASSERT: returned element (%@) should test false for Comment");
        STAssertNotNil([e srcTxt], @"ASSERT: srcTxt should not be nil");
        if (nil != [e srcTxt]) {
            STAssertEqualObjects(EMPTY_STRING, 
                                 [e srcTxt], 
                                 @"srcText should be empty string but it \"%@\" instead", 
                                 [e srcTxt]);
        } // if
    } // if
    
    e = [lexer nextElement];
    STAssertNil(e, @"ASSERT: returned element should be nil, but is %@", e);
    
    [lexer release];
    
    lexer = [[QEADIFLexer alloc] initWithSrc:EMPTY_STRING];
    STAssertNotNil(lexer, @"ASSERT: failed to allocate lexer when using empty string as source");
    e = [lexer nextElement];
    STAssertNotNil(e, @"ASSERT: returned nil element instead of expected EOInput element");
    if (nil != e) {
        STAssertTrue([e isEOInput], @"ASSERT: returned element (%@) should test true for EOInput");
        STAssertTrue(1 == [e startLine], @"ASSERT: element startLine should be 1 but it is %u",
                     [e startLine]);
        STAssertTrue(1 == [e startPos], @"ASSERT: element startPos should be 1 but it is %u",
                     [e startPos]);
        STAssertFalse([e isField], @"ASSERT: returned element (%@) should test false for Field");
        STAssertFalse([e isTag], @"ASSERT: returned element (%@) should test false for Tag");
        STAssertFalse([e isComment], @"ASSERT: returned element (%@) should test false for Comment");
        STAssertNotNil([e srcTxt], @"ASSERT: srcTxt should not be nil");
        if (nil != [e srcTxt]) {
            STAssertEqualObjects(EMPTY_STRING, 
                                 [e srcTxt], 
                                 @"srcText should be empty string but it \"%@\" instead", 
                                 [e srcTxt]);
        } // if
    } // if
    
    e = [lexer nextElement];
    STAssertNil(e, @"ASSERT: returned element should be nil, but is %@", e);
    
    [lexer release];
} // testBlankSource


- (void)testAnalysis
{
    NSEnumerator *expectedTags;
    NSString *expectedTag;
    NSString *actualTag;
    
    QEADIFLexer *lexer = [[QEADIFLexer alloc] initWithSrc:ADIF_SRC1_LF];
    expectedTags = [ADIF_SRC1_LF_TAGS objectEnumerator];
    while (nil != (expectedTag = [expectedTags nextObject])) {
        id element = [lexer nextElement];
        if (nil != element) {
            actualTag = [element description];
        } // if
        STAssertEqualObjects(expectedTag, actualTag,
                             @"ASSERT: expected tag: %@; actual tag: %@",
                             expectedTag, actualTag);
    } // while
    [lexer release];
    
    lexer = [[QEADIFLexer alloc] initWithSrc:ADIF_SRC1_CR];
    expectedTags = [ADIF_SRC1_CR_TAGS objectEnumerator];
    while (nil != (expectedTag = [expectedTags nextObject])) {
        id element = [lexer nextElement];
        if (nil != element) {
            actualTag = [element description];
        } // if
        STAssertEqualObjects(expectedTag, actualTag,
                             @"ASSERT: expected tag: %@; actual tag: %@",
                             expectedTag, actualTag);
    } // while
    [lexer release];
    
    lexer = [[QEADIFLexer alloc] initWithSrc:ADIF_SRC1_CRLF];
    expectedTags = [ADIF_SRC1_CRLF_TAGS objectEnumerator];
    while (nil != (expectedTag = [expectedTags nextObject])) {
        id element = [lexer nextElement];
        if (nil != element) {
            actualTag = [element description];
        } // if
        STAssertEqualObjects(expectedTag, actualTag,
                             @"ASSERT: expected tag: %@; actual tag: %@",
                             expectedTag, actualTag);
    } // while
    [lexer release];
} // testAnalysis
@end
